#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <stdio.h>
#include <time.h>

#include <sys/stat.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

//#include <error.h>
#include <errno.h>
#include <stdarg.h>
#include <getopt.h>

#include <mysql/errmsg.h>
#include <mysql/mysql.h>

#define MAX_QUERY_LEN			4096
#define MAX_STRING_LEN			MAX_QUERY_LEN
#define SQL_DOWN			1 
#define MAX_COMMUNITY_LEN		50
#define MAX_SQL_SOCKS			256
#define MAX_TABLE_LEN			20
#define MAX_AUTH_QUERY_LEN		256
#define AUTH_STRING_LEN			128
#define QLEN				10
#define MBUF    			64
#define SBUF     			128
#define DBPOOL				20
#define BMAX				1024
#define SXMAX 				200
#define ARMAX 				0xFFFF
#define FOUND 				0
#define NOTFOUND			1
#define M1LEN 				39
#define M2LEN 				1024
#define MXM1				M1LEN*M1LEN
#define INTMAX  			65535

#define FAIL  (-1)
#define SUCCEED (0)
#define  TCLICK 1000

typedef char** SQL_ROW;

typedef unsigned int u_int32_t;


typedef struct sql_mysql_sock {
	MYSQL conn;
	MYSQL *sock;
	MYSQL_RES *result;
	SQL_ROW row;
	int cur_row;
	int num_fields;
	int affected_rows;
	int id;
	char ftrace[QLEN];
} SQL_SOCK;

typedef struct sql_config {

	char   *sql_server;
	char   *sql_port;
	char   *sql_login;
	char   *sql_password;
	char   *sql_db;
	
} SQL_CONFIG;

typedef struct 
{ 
SQL_SOCK   *sock;
pthread_mutex_t mutex;
time_t		connect_after;
int state;
SQL_CONFIG	*config;

} SQL_SOCK_POOL;


#define	TYPE_INT	0
#define	TYPE_STRING	1

#define	PARM_OPT	0
#define	PARM_MAND	1

struct cfg_line
{
	char	*parameter;
	void	*variable;
	int	(*function)();
	int	type;
	int	mandatory;
	int	min;
	int	max;
};

typedef struct COMB_DNS
{
  unsigned long ipserial;
  char ip[24];
  char name[1024];
  unsigned long long ncount;
  unsigned int ip_id;
  struct COMB_DNS *next;
} ICDNS;

typedef struct  ARRAY_DNS
{
  char *name; 
  unsigned long ncount;
  struct ARRAY_DNS *next;
} NCDNS;


typedef struct  ARRAY_IP
{
  unsigned long ncount;
  unsigned long ip_id;
  
} IARRAY;

typedef struct  iplist
{
   unsigned long ip_id;
   char *ipstart;
   char *ipstop;
   struct iplist *next;
} IPL;

unsigned long mcnt = 0L;

int ctable[] = { -1,
   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
   -1,  39,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
   -1,  -1,  -1,  -1,  37,  38,  -1,   0,   1,   2,
    3,   4,   5,   6,   7,   8,   9,  10,  -1,  -1,
   -1,  -1,  -1,  -1,  11,  12,  13,  14,  15,  16,
   17,  18,  19,  20,  21,  22,  23,  24,  25,  26,
   27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
   -1,  -1,  -1,  -1,  39,  -1,  11,  12,  13,  14,
   15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
   25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
   35,  36,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
};

char *help_message[] = {
        "Options:",
        "  -c --config <config file>       Specify configuration file",
        "  -h --help                give this help",
        "  -f --file  <file> convert dns query log data to db",
        "  -v --version             display version number",
        "Program name statuslog for DNS status log",
        "Program name cstatuslog for CNS status log",
        "Others for bind9.4 Query Log",
        0 /* end of text */
};

struct option longopts[] =
{
	{"config",	1,	0,	'c'},
	{"help",	0,	0,	'h'},
	{"file",	1,	0,	'f'},
	{"version",	0,	0,	'v'},
	{0,0,0,0}
};

char *progname = NULL;
char usage_message[] = "[-hv] [-c <config file>][-f <querylog>]";


int m1table[M1LEN];
int m2table[MXM1][M2LEN];

long long MAXSEQ=0;
long long curseq=0;


#define LOG_LEVEL_EMPTY	0
#define LOG_LEVEL_CRIT		1
#define LOG_LEVEL_ERR		2
#define LOG_LEVEL_WARNING	3
#define LOG_LEVEL_DEBUG	4
#define LOG_LEVEL_MSG		5
#define LOG_TYPE_UNDEFINED	0
#define LOG_TYPE_SYSLOG		1
#define LOG_TYPE_FILE		2

char	*CONFIG_LOG_FILE		= NULL;
int	CONFIG_LOG_LEVEL		= LOG_LEVEL_ERR;

char	*CONFIG_FILE			= NULL;
char	*CONFIG_DBUSER			= NULL;
char	*CONFIG_DBSOCKET		= NULL;
char	*CONFIG_DBHOST			= NULL;
char	*CONFIG_DBNAME			= NULL;
char	*CONFIG_DBLOGIN			= NULL;
char	*CONFIG_DBPASSWORD		= NULL;
char	*CONFIG_DBPORT			=NULL;
int	CONFIG_HOSTID=1;
int	CONFIG_DBPOOL=10;
char	*DNS_LOG_FILE			=NULL;


int  CONFIG_IPLOW=0;
int CONFIG_ASLOW=0;

long long atoll(const char * );
#define strscpy(x,y) { strncpy(x,y,sizeof(x)); x[sizeof(x)-1]=0; }

pthread_mutex_t 	plock;
pthread_mutex_t		loglocked;

SQL_SOCK_POOL  glb_conn[DBPOOL];


char *query1="select count(*) from host_template";
char *logquery="select count(*) from querylog where rec_date='%s'";
char *idquery="select max(id) from querylog where rec_date='%s'";
char *idquery2="select max(id) from querylog";
char *createiptbl="create table ip_detail%s like ip_detail";
char *createnametbl="create table name_detail%s like name_detail";
char *chk_ip_latency="select value from settings where name='bind_ip_latency'";
char *chk_name_latency="select value from settings where name='bind_name_latency'";
char *get_iplist="select id,ipstart,ipstop,disabled from iplist";
char *ins_querylog="insert into querylog (id,host_id,rec_date,status) values ('%lu','%lu','%s','UN')";
char *ins_ip="insert into ip_detail%s (query_id, ip, counts,rec_date) values ( '%lu', '%s', '%lu','%s')";
char *ins_name="insert into name_detail%s (query_id, name, counts,rec_date) values ( '%lu', '%s', '%lu','%s')";
char *update_querylog="update querylog set status='UN',log_lines='%lu', ip_counts='%lu', name_counts='%lu', ip_below='%lu', name_below='%lu' where id='%lu'";
char *ins_ipsummary="insert into ipsummary (ip_id,ipcounts) values ('%lu','%lu')";
char *ins_status_last="insert  into statuslog (host_id,status,success,referral,nxrrset,nxdomain,recursion,failure,duplicate,dropped,servfail,redirect,rec_date) values ('%lu','LAST','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%s')";
char *update_status_last="update  statuslog  set success='%lu',referral='%lu',nxrrset='%lu',nxdomain='%lu',recursion='%lu',failure='%lu',duplicate='%lu',dropped='%lu',servfail='%lu',redirect='%lu',rec_date=now() where  host_id='%lu' and status='LAST'";
char *ins_status="insert into statuslog (host_id,status,success,referral,nxrrset,nxdomain,recursion,failure,duplicate,dropped,servfail,redirect,rec_date) values ('%lu','UN','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%s')";
char *cins_status_last="insert into statuslog (host_id,status,success,referral,nxrrset,nxdomain,recursion,failure,duplicate,dropped,servfail,redirect,rec_date) values ('%lu','LAST','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%s')";
char *cins_update_status_last="update statuslog set success='%lu',referral='%lu',nxrrset='%lu',nxdomain='%lu',recursion='%lu',failure='%lu',duplicate='%lu',dropped='%lu',servfail='%lu',redirect='%lu',rec_date=now() where  host_id='%lu' and status='LAST'";
char *cins_status="insert into statuslog (host_id,status,success,referral,nxrrset,nxdomain,recursion,failure,duplicate,dropped,servfail,redirect,rec_date) values ('%lu','UN','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%lu','%s')";
char *select_status="select ifnull(success,0),ifnull(referral,0),ifnull(nxrrset,0),ifnull(nxdomain,0),ifnull(recursion,0),ifnull(failure,0),ifnull(duplicate,0),ifnull(dropped,0),ifnull(servfail,0),ifnull(redirect,0),ifnull(rec_date,now()) 	from statuslog where host_id=%u and  status='LAST'";


static	FILE *log_file = NULL;
static	char log_filename[MAX_STRING_LEN];
static	int log_type = LOG_TYPE_UNDEFINED;
static	int log_level;

void usage()
{
	printf("usage: %s %s\n", progname, usage_message);
}

void version()
{
	printf("Compilation time:  %s %s\n", __DATE__, __TIME__);
}

void help()
{
	char **p = help_message;
	
	printf("\n");
	usage();
	printf("\n");
	while (*p) printf("%s\n", *p++);
}

int logp_open_log(int type,int level, const char *filename)
{
/* Just return if we do not want to write debug */
	log_level = level;
	if(level == LOG_LEVEL_EMPTY)
	{
		return	SUCCEED;
	}

	if(type == LOG_TYPE_SYSLOG)
	{
        	openlog("dns logp",LOG_PID,LOG_USER);
        	setlogmask(LOG_UPTO(LOG_WARNING));
		log_type = LOG_TYPE_SYSLOG;
	}
	else if(type == LOG_TYPE_FILE)
	{
		log_file = fopen(filename,"a+");
		if(log_file == NULL)
		{
			fprintf(stderr, "Unable to open debug file [%s] [%m]\n", filename);
			return	FAIL;
		}
		log_type = LOG_TYPE_FILE;
		strscpy(log_filename,filename);
		fclose(log_file);
	}
	else
	{
/* Not supported logging type */
		fprintf(stderr, "Not supported loggin type [%d]\n", type);
		return	FAIL;
	}
	return	SUCCEED;
}

void logp_set_log_level(int level)
{
	log_level = level;
}

void logp_log(int level, const char *fmt, ...)
{
	char	str[MAX_STRING_LEN];
	char	str2[MAX_STRING_LEN];
	time_t	t;
	struct	tm	*tm;
	va_list ap;

	struct stat	buf;
	char	filename_old[MAX_STRING_LEN];
	
	if((level>log_level) || (level == LOG_LEVEL_EMPTY))
	{
		return;
	}

	if(log_type == LOG_TYPE_SYSLOG)
	{
		va_start(ap,fmt);
		vsprintf(str,fmt,ap);
		strncat(str,"\n",MAX_STRING_LEN);
		str[MAX_STRING_LEN]=0;
		syslog(level,str);
		va_end(ap);
	}
	else if(log_type == LOG_TYPE_FILE)
	{
		t=time(NULL);
		tm=localtime(&t);
		snprintf(str2,sizeof(str2)-1,"%.6d:%.4d%.2d%.2d:%.2d%.2d%.2d ",(int)getpid(),tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);

		va_start(ap,fmt);
		vsnprintf(str,MAX_STRING_LEN,fmt,ap);
		pthread_mutex_lock(&loglocked);
		log_file = fopen(log_filename,"a+");
		if(log_file == NULL)
		{
			return;
		}
		fprintf(log_file,"%s",str2);
		fprintf(log_file,"%s",str);
		fprintf(log_file,"\n");
		fclose(log_file);
		va_end(ap);
		pthread_mutex_unlock(&loglocked);

		if(stat(log_filename,&buf) == 0)
		{
			if(buf.st_size>1024*1024)
			{
				strscpy(filename_old,log_filename);
				strncat(filename_old,".old",MAX_STRING_LEN);
				if(rename(log_filename,filename_old) != 0)
				{
/*					exit(1);*/
				}
			}
		}
	}
	else
	{
		/* Log is not opened */
	}	
        return;
}



int	parse_cfg_file(char *cfg_file,struct cfg_line *cfg)
{
	FILE	*file;
	char	line[MAX_STRING_LEN];
	char	parameter[MAX_STRING_LEN];
	char	*value;
	int	lineno;
	int	i,var;
	char	**c;
	int	(*func)();



	file=fopen(cfg_file,"r");
	if(NULL == file)
	{
		fprintf(stderr, "Cannot open config file [%s] [%m]\n",cfg_file);
		return	FAIL;
	}

	lineno=0;
	while(fgets(line,MAX_STRING_LEN,file) != NULL)
	{
		lineno++;

		if(line[0]=='#')	continue;
		if(strlen(line)==1)	continue;

		strscpy(parameter,line);

		value=strstr(line,"=");

		if(NULL == value)
		{
			fprintf(stderr, "Error in line [%s] Line %d\n", line, lineno);
			return	FAIL;
		}
		value++;
		value[strlen(value)-1]=0;

		parameter[value-line-1]=0;

		i=0;
		while(cfg[i].parameter != 0)
		{
			if(strcmp(cfg[i].parameter, parameter) == 0)
			{
				if(cfg[i].function != 0)
				{
					func=cfg[i].function;
					if(func(value)!=SUCCEED)
					{
						fprintf(stderr, "Wrong value of [%s] in line %d.\n", cfg[i].parameter, lineno);
						return	FAIL;
					}
				}
				else
				{
				if(cfg[i].type == TYPE_INT)
				{
					var=atoi(value);
					if( (cfg[i].min!=0) || (cfg[i].max!=0))
					{
						if( (var<cfg[i].min) || (var>cfg[i].max) )
						{
							fprintf(stderr, "Wrong value of [%s] in line %d. Should be between %d and %d.\n", cfg[i].parameter, lineno, cfg[i].min, cfg[i].max);
							return	FAIL;
						}
						
					}
					*((int*)cfg[i].variable)=var;
				}
				else
				{
/* Can this be done without "c" ? */ 
					c=(char **)cfg[i].variable;
					*c=(char *)strdup(value);
/*					*((char*)cfg[i].variable)=strdup(value);*/
				}
				}
			}
			i++;
		}
	}

/* Check for mandatory parameters */
	i=0;
	while(cfg[i].parameter != 0)
	{
		if(cfg[i].mandatory ==1)
		{
			if(cfg[i].type == TYPE_INT)
			{
/*				pointer=(int *)cfg[i].variable;
				if(*pointer==0)*/
				if(*((int*)cfg[i].variable) == 0)
				{
					fprintf(stderr,"Missing mandatory parameter [%s]\n", cfg[i].parameter);
					return	FAIL;
				}
			}
			if(cfg[i].type == TYPE_STRING)
			{
				c=(char **)cfg[i].variable;
				if(*c==NULL)
				{
					fprintf(stderr, "Missing mandatory parameter [%s]\n", cfg[i].parameter);
					return	FAIL;
				}
			}
		}
		i++;
	}

	return	SUCCEED;
}


void	init_config(void)
{
static struct cfg_line cfg[]=
{
/*		 PARAMETER	,VAR	,FUNC,	TYPE(0i,1s),MANDATORY,MIN,MAX	*/
{"LogFile",&CONFIG_LOG_FILE,0,TYPE_STRING,PARM_OPT,0,0},
{"DBHost",&CONFIG_DBHOST,0,TYPE_STRING,PARM_OPT,0,0},
{"DBName",&CONFIG_DBNAME,0,TYPE_STRING,PARM_MAND,0,0},
{"DBLogin",&CONFIG_DBLOGIN,0,TYPE_STRING,PARM_MAND,0,0},
{"DBPassword",&CONFIG_DBPASSWORD,0,TYPE_STRING,PARM_OPT,0,0},
{"DBPort",&CONFIG_DBPORT,0,TYPE_STRING,PARM_OPT,0,0},
{"DBPool",&CONFIG_DBPOOL,0,TYPE_INT,PARM_OPT,0,19},
{"IPLatency",&CONFIG_IPLOW,0,TYPE_INT,PARM_OPT,0,0},
{"HostID",&CONFIG_HOSTID,0,TYPE_INT,PARM_OPT,0,10000},
{"DOMAINLatency",&CONFIG_ASLOW,0,TYPE_INT,PARM_OPT,0,0},
{0}
};

if(CONFIG_FILE == NULL)
	{
		CONFIG_FILE=strdup("/etc/logprocess.conf");
	}

parse_cfg_file(CONFIG_FILE,cfg);


if(CONFIG_DBNAME == NULL)
{
logp_log(LOG_LEVEL_ERR, "DBName not in config file");
exit(1);
}


}




ICDNS *
find_ipserial (ICDNS * hd, u_int32_t ipserial)
{
  ICDNS *cur, *pre;
  if (hd == NULL)
    {
      return (NULL);
    }
  cur = hd;
  unsigned long cnt = 0L;

  while (cur != NULL)
    {
      pre = cur;
      if (cur->ipserial == ipserial)
        {
          return (cur);
        }
      cur = cur->next;
      cnt++;
      if (cnt > 100000 * (mcnt + 1))
        {
          mcnt++;
          cnt = 0L;
        }
    }

  pre->next = malloc (sizeof (ICDNS));
  pre = pre->next;
  return pre;


}

int xnamehash(NCDNS  *a1, char *s)
{
  int x, r, i;
  char c;
  unsigned int first;
  x = r = 0;
  NCDNS  *ii,*pre,*cur;
  int result;
  ii=a1;
  if(s==NULL) return 0;
  
  first=(int)s[0]*(int)s[1];
  first%=MXM1;

//  for (i = 0; i < strlen(s); i++)
  i=0;
while(s[i]!=0x0)
    {
      r = (x >>27) & 0x7f;
      x <<= 5;
      x |= r;

      c = (char)s[i];
      if(ctable[c]>=0)
        x ^= ( c & 0x7f);
	i++;
    }

  i=((x+m2table[first][x&0x3ff])&0xffff);

cur=(NCDNS *)&a1[i];

result=NOTFOUND;
x=strlen(s);
 while(cur!=NULL)
   {
     pre=cur;
     if(cur->name==NULL) break; 
     if(strncmp(s,cur->name,x)==0)
     {
      cur->ncount++;
      result=FOUND; 
      break;
     }
     else
       { 
         cur=cur->next; 
       }
   }


if(result==NOTFOUND)
   {
     if(pre->name==NULL)
      {
    logp_log(LOG_LEVEL_DEBUG,"First %s %d\n",s,i);
      pre->name=malloc(sizeof(char)*(x+1));
      pre->next=NULL; 
      cur=pre;
      }
     else
     {
      
   logp_log(LOG_LEVEL_DEBUG,"Found  %s %d\n",s,i);
     pre->next=malloc(sizeof(NCDNS));
     cur=pre->next;
     cur->name=malloc(sizeof(char)*(x+1));
     cur->next=NULL; 
     }
    memcpy(cur->name,s,x+1);
     cur->ncount=1L;
}
  
 return result;

 }

int
namehash (unsigned int **a1,NCDNS *s)
{
  int x, r, i;
  char c;
  x = r = 0;
  unsigned int **ii;
  ii=a1;

  for (i = 0; i < strlen (s->name); i++)
    {
      r = (x >> 24) & 255;
      x <<= 8;
      x ^= r;
      x |= (r >> 1);
      c = (char) s->name[i];
 
     x |= ((ctable[c & 0x7f]) & 255);
    }

 i=(ii[x&0xffff][(x&0xffff0000)>>16])++;
 if(i) s->ncount++;
 return i;
  
}


u_int32_t
xaton (char *s)
{
  u_int32_t a, b, c, d;

  if (4 != sscanf (s, "%d.%d.%d.%d", &a, &b, &c, &d))
    return FAIL;
  return ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | (d &  0xFF);
}

int
dxaton (IARRAY **a1, char *s)
{
  u_int32_t a, b, c, d;
  int i = 0;
  IARRAY **ii, *p;
  ii = a1;

  if (4 != sscanf (s, "%d.%d.%d.%d", &a, &b, &c, &d))
    return FAIL;
  p=&ii[((a & 0xFF) << 8) | (b & 0xFF)][((c & 0xFF) << 8) | (d & 0xFF)];
  i = p->ncount++;
  return i;

}

int
sxarray (IARRAY **a1, char *s)
{
  u_int32_t a, b, c, d;
  int i = 0;
  IARRAY **ii,*p;
  ii = a1;

  if (4 != sscanf (s, "%d.%d.%d.%d", &a, &b, &c, &d))
    return FAIL;
  p = &ii[((a & 0xFF) << 8) | (b & 0xFF)][((c & 0xFF) << 8) | (d & 0xFF)];
  i=p->ncount;
  return i;

}
/*************************************************************************
 *
 *	Function: sql_create_socket
 *
 *	Purpose: Establish connection to the db
 *
 *************************************************************************/
static int sql_init_socket(SQL_SOCK *sqlsocket,SQL_CONFIG *config)
{
 	SQL_SOCK  *mysql_sock;
/*
	if (!sqlsocket->conn) {
		sqlsocket->conn = (MYSQL  *)malloc(sizeof(MYSQL));
		if (!sqlsocket->conn) {
			return -1;
		}
	}

*/

mysql_sock= sqlsocket;

	logp_log(LOG_LEVEL_DEBUG, "sql_mysql: Starting connect to MySQL server for #%d",
			sqlsocket->id);

	mysql_init(&mysql_sock->conn);
	mysql_options(&mysql_sock->conn, MYSQL_READ_DEFAULT_GROUP, "cacti");
	if (!(mysql_sock->sock = mysql_real_connect(&mysql_sock->conn,
						    config->sql_server,
						    config->sql_login,
						    config->sql_password,
						    config->sql_db,
						    atoi(config->sql_port),
						    NULL,
						    0))) {
		logp_log(LOG_LEVEL_ERR, "sql_mysql: Couldn't connect socket to MySQL server %s@%s:%s", config->sql_login, config->sql_server, config->sql_db);
		logp_log(LOG_LEVEL_ERR, "sql_mysql: Mysql error '%s'", mysql_error(&mysql_sock->conn));
		mysql_sock->sock=NULL;
		return FAIL;
	}


	return 0;
}


/*************************************************************************
 *
 *	Function: sql_destroy_socket
 *
 *	Purpose: Free socket and any private connection data
 *
 *************************************************************************/
static int sql_destroy_socket(SQL_SOCK *sqlsocket)
{
	free(sqlsocket->sock);
	sqlsocket->sock=NULL;
	return 0;
}


/*************************************************************************
 *
 *	Function: sql_check_error
 *
 *	Purpose: check the error to see if the server is down
 *
 *************************************************************************/
static int sql_check_error(int error)
{
	switch(error) {
	case CR_SERVER_GONE_ERROR:
	case CR_SERVER_LOST:
	case -1:
		logp_log(LOG_LEVEL_DEBUG, "sql_mysql: MYSQL check_error: %d, returning SQL_DOWN", error);
		return SQL_DOWN;
		break;
	case 0:
		return 0;
		break;
	case CR_OUT_OF_MEMORY:
	case CR_COMMANDS_OUT_OF_SYNC:
	case CR_UNKNOWN_ERROR:
	default:
		logp_log(LOG_LEVEL_DEBUG, "sql_mysql: MYSQL check_error: %d received", error);
		return -1;
		break;
	}
}


/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a query to the database
 *
 *************************************************************************/
static int sql_query(SQL_SOCK * sqlsocket, char *querystr)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	logp_log(LOG_LEVEL_DEBUG,"sql_mysql: query:  %s", querystr);
	if (mysql_sock->sock == NULL) {
		logp_log(LOG_LEVEL_ERR, "sql_mysql: Socket not connected");
		return SQL_DOWN;
	}

	mysql_query(mysql_sock->sock, querystr);
	return sql_check_error(mysql_errno(mysql_sock->sock));
}


/*************************************************************************
 *
 *	Function: sql_store_result
 *
 *	Purpose: database specific store_result function. Returns a result
 *               set for the query.
 *
 *************************************************************************/
static int sql_store_result(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	if (mysql_sock->sock == NULL) {
		logp_log(LOG_LEVEL_ERR, "sql_mysql: Socket not connected");
		return SQL_DOWN;
	}
	if (!(mysql_sock->result = mysql_store_result(mysql_sock->sock))) {
		logp_log(LOG_LEVEL_ERR, "sql_mysql: MYSQL Error: Cannot get result");
		logp_log(LOG_LEVEL_ERR, "sql_mysql: MYSQL Error: %s",
		       mysql_error(mysql_sock->sock));
		return sql_check_error(mysql_errno(mysql_sock->sock));
	}
	return 0;
}


/*************************************************************************
 *
 *	Function: sql_num_fields
 *
 *	Purpose: database specific num_fields function. Returns number
 *               of columns from query
 *
 *************************************************************************/
static int sql_num_fields(SQL_SOCK * sqlsocket)
{
	int     num = 0;
	SQL_SOCK *mysql_sock = sqlsocket;

#if MYSQL_VERSION_ID >= 32224
	if (!(num = mysql_field_count(mysql_sock->sock))) {
#else
	if (!(num = mysql_num_fields(mysql_sock->sock))) {
#endif
		logp_log(LOG_LEVEL_ERR, "sql_mysql: MYSQL Error: No Fields");
		logp_log(LOG_LEVEL_ERR, "sql_mysql: MYSQL error: %s",
		       mysql_error(mysql_sock->sock));
	}
	return num;
}


/*************************************************************************
 *
 *	Function: sql_select_query
 *
 *	Purpose: Issue a select query to the database
 *
 *************************************************************************/
static int sql_select_query(SQL_SOCK *sqlsocket,
			    char *querystr)
{
	int ret;

	ret = sql_query(sqlsocket, querystr);
	if(ret)
		return ret;
	ret = sql_store_result(sqlsocket);
	if (ret) {
		return ret;
	}

	/* Why? Per http://www.mysql.com/doc/n/o/node_591.html,
	 * this cannot return an error.  Perhaps just to complain if no
	 * fields are found?
	 */
	sql_num_fields(sqlsocket);

	return ret;
}


/*************************************************************************
 *
 *	Function: sql_num_rows
 *
 *	Purpose: database specific num_rows. Returns number of rows in
 *               query
 *
 *************************************************************************/
static int sql_num_rows(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	if (mysql_sock->result)
		return mysql_num_rows(mysql_sock->result);

	return 0;
}


/*************************************************************************
 *
 *	Function: sql_fetch_row
 *
 *	Purpose: database specific fetch_row. Returns a SQL_ROW struct
 *               with all the data for the query in 'sqlsocket->row'. Returns
 *		 0 on success, -1 on failure, SQL_DOWN if database is down.
 *
 *************************************************************************/
static int sql_fetch_row(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	/*
	 *  Check pointer before de-referencing it.
	 */
	if (!mysql_sock->result) {
		return SQL_DOWN;
	}

	sqlsocket->row = mysql_fetch_row(mysql_sock->result);

	if (sqlsocket->row == NULL) {
		return sql_check_error(mysql_errno(mysql_sock->sock));
	}
	return 0;
}


/*************************************************************************
 *
 *	Function: sql_free_result
 *
 *	Purpose: database specific free_result. Frees memory allocated
 *               for a result set
 *
 *************************************************************************/
static int sql_free_result(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	if (mysql_sock->result) {
		mysql_free_result(mysql_sock->result);
		mysql_sock->result = NULL;
	}

	return 0;
}



/*************************************************************************
 *
 *	Function: sql_error
 *
 *	Purpose: database specific error. Returns error associated with
 *               connection
 *
 *************************************************************************/
const char *sql_error(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	if (mysql_sock == NULL || mysql_sock->sock == NULL) {
		return "sql_mysql: no connection to db";
	}
	return mysql_error(mysql_sock->sock);
}


/*************************************************************************
 *
 *	Function: sql_close
 *
 *	Purpose: database specific close. Closes an open database
 *               connection
 *
 *************************************************************************/
static int sql_close(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	if (mysql_sock && mysql_sock->sock){
		mysql_close(mysql_sock->sock);
		mysql_sock->sock = NULL;
	}

	return 0;
}


/*************************************************************************
 *
 *	Function: sql_finish_query
 *
 *	Purpose: End the query, such as freeing memory
 *
 *************************************************************************/
static int sql_finish_query(SQL_SOCK * sqlsocket)
{
	return 0;
}



/*************************************************************************
 *
 *	Function: sql_finish_select_query
 *
 *	Purpose: End the select query, such as freeing memory or result
 *
 *************************************************************************/
static int sql_finish_select_query(SQL_SOCK * sqlsocket)
{
	sql_free_result(sqlsocket);

	return 0;
}


/*************************************************************************
 *
 *	Function: sql_affected_rows
 *
 *	Purpose: End the select query, such as freeing memory or result
 *
 *************************************************************************/
static int sql_affected_rows(SQL_SOCK * sqlsocket)
{
	SQL_SOCK *mysql_sock = sqlsocket;

	return mysql_affected_rows(mysql_sock->sock);
}

SQL_SOCK *get_sql_socket()
{
    int ora_point,retry;
    SQL_SOCK *cur;

   
	retry=0;
        while(retry<5)
        {
      
        	ora_point=0;
                while (ora_point<CONFIG_DBPOOL)
                {
                cur=glb_conn[ora_point].sock;
                if (pthread_mutex_trylock(&glb_conn[ora_point].mutex) == 0)
                 {

                  if(glb_conn[ora_point].state==0)
                        {glb_conn[ora_point].state=1;
				 glb_conn[ora_point].sock->id=ora_point+1;

			    pthread_mutex_unlock(&glb_conn[ora_point].mutex);
                         return glb_conn[ora_point].sock;
                        }
                else pthread_mutex_unlock(&glb_conn[ora_point].mutex);

                }			

                ora_point++;
                }
        retry++;
	 usleep(TCLICK);
        }
        logp_log(LOG_LEVEL_ERR,"No Oracle connection usable");
        return(NULL);
}



int release_sql_socket(SQL_SOCK *sql_sock)
{
    int ora_point=0;
    SQL_SOCK *cur;


                while (ora_point<CONFIG_DBPOOL)
                {
                 cur=glb_conn[ora_point].sock;


                  if(glb_conn[ora_point].sock->id==cur->id)
                  	 if (pthread_mutex_trylock(&glb_conn[ora_point].mutex) == 0)
                      {
			   glb_conn[ora_point].state=0;glb_conn[ora_point].sock->id=0;
			   memset(glb_conn[ora_point].sock->ftrace,0x0,sizeof(glb_conn[ora_point].sock->ftrace));
                        pthread_mutex_unlock(&glb_conn[ora_point].mutex);
                         return 0;
                        }
		 
                  ora_point++;
         }

        logp_log(LOG_LEVEL_ERR,"No postgresql connection usable");
        return(-1);
}


int
main (int argc, char **argv)
{
 
  int sockfd;
  int i,j,ret,ch;
  
  SQL_CONFIG  mydb_conf;
  SQL_SOCK  *sqlsock,*inssock;
  char sql[MAX_STRING_LEN];
  char cur_date[SBUF];
  char cur_daily[SBUF];

 int option_index = 0;
 progname = argv[0];

 time_t t_now;
 struct tm *runtime;
 
 ICDNS *ip_cdns, *ip_hd,*ip_cur,*name_cdns;
 NCDNS  *name_hd, *name_cur;
 
 FILE *fh;
 char fbuf[BMAX];
 unsigned long  line_counts=0L;
 char tmp1[MBUF],tmp2[MBUF],ipbuf[SXMAX],namebuf[SXMAX];
 unsigned int tmpint;
 int havelast;
 char *tmpchar;
 int rantmp, ranhp;

 unsigned long int queryid;  
 unsigned long int below_ip=0L,below_name=0L;
 unsigned long int ip_cnt=0L,name_cnt=0L;

unsigned int s_success,s_referral,s_nxrrset,s_nxdomain,s_recursion,s_failure;
unsigned long int bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bservfail,bredirect,bduplicate,bdropped;
unsigned long int success,referral,nxrrset,nxdomain,recursion,failure,servfail,redirect,duplicate,dropped;
unsigned int total_status;

unsigned int maxline=0;
unsigned long int maxslots=0L;
 
 int sxcnt=0;
 IARRAY **iparray;
 NCDNS *ap; 
 NCDNS *namearray = malloc (INTMAX* sizeof (NCDNS));

IPL  *ipl_hd, *ipl_cur, *ipl_next;
int ipl_label,ipl_label1,ipl_label2;
unsigned long ipl_count;

 
if(argc<2) { usage(); exit(-1);}
 
while ((ch = getopt_long(argc, argv, "c:f:hv",longopts,NULL)) != EOF)
	switch ((char) ch) {
		case 'c':
			CONFIG_FILE = strdup(optarg);
			break;
		case 'h':
			help();
			exit(-1);
			break;
		case 'f':
			DNS_LOG_FILE=strdup(optarg);
			break;
		case 'v':
			version();
			exit(-1);
			break;
		default:
			usage();
			exit(-1);
			break;
        }

t_now= time (NULL);
runtime= localtime (&t_now);
snprintf(cur_date,sizeof(cur_date)-1,"%04d_%02d_%02d %02d:%02d:%02d",runtime->tm_year+1900,runtime->tm_mon+1,runtime->tm_mday,
			runtime->tm_hour,runtime->tm_min,runtime->tm_sec);

snprintf(cur_daily,sizeof(cur_daily)-1,"%04d_%02d_%02d",runtime->tm_year+1900,runtime->tm_mon+1,runtime->tm_mday);

if(CONFIG_LOG_FILE == NULL)
	{
	logp_open_log(LOG_TYPE_SYSLOG,CONFIG_LOG_LEVEL,NULL);
	}
	else
	{
	  logp_open_log(LOG_TYPE_FILE,CONFIG_LOG_LEVEL,CONFIG_LOG_FILE);
	}

init_config();

if((CONFIG_DBHOST==NULL)||(CONFIG_DBNAME==NULL))
      {
         logp_log(LOG_LEVEL_CRIT,"%s configure file %s not correct",progname,CONFIG_FILE);
	exit(-1);
      }

if(DNS_LOG_FILE==NULL)
{
  logp_log(LOG_LEVEL_CRIT," dns query log file %s not correct",DNS_LOG_FILE);
   exit(-1);
}

  mydb_conf.sql_server=strdup(CONFIG_DBHOST);
  mydb_conf.sql_login=strdup(CONFIG_DBLOGIN);
  mydb_conf.sql_password=strdup(CONFIG_DBPASSWORD);
  mydb_conf.sql_db=strdup(CONFIG_DBNAME);
  mydb_conf.sql_port=strdup(CONFIG_DBPORT);
  
  for(i=0;i<CONFIG_DBPOOL;i++)
  	{
  	  pthread_mutex_init(&glb_conn[i].mutex,NULL);
	  glb_conn[i].sock=(SQL_SOCK *)malloc(sizeof(SQL_SOCK));
  	  if((ret=sql_init_socket(glb_conn[i].sock, &mydb_conf))==FAIL)
	  	{	
	  		logp_log(LOG_LEVEL_ERR,"Error in building mysql connect");
	  		exit(0);
		}
  	}

havelast=FAIL;
if(strstr(progname,"cstatuslog")!=0)
{
/*
>            queries => '9553028'
>            lookups => '14180432'
>            recursive-lookups => '2485078'
>            rejected-responses => '0'
>            id-spoofing-defense-queries => '29'
>            replaced-nxdomains => '469054'
>            responses-by-rcode => {
>            noerror => '7638061'
>            servfail => '1728530'
>            nxdomain => '186389'
*/

s_success=s_referral=s_nxrrset=s_nxdomain=s_recursion=s_failure=SUCCEED;
bsuccess=breferral=bnxrrset=bnxdomain=brecursion=bfailure=bduplicate=bdropped=bservfail=bredirect=123L;
success=referral=nxrrset=nxdomain=recursion=failure=duplicate=dropped=servfail=redirect=0L;
total_status=SUCCEED;

if ((fh = fopen (DNS_LOG_FILE, "r")) == NULL)
	{
	  printf ("Error: can't open file %s.\n",DNS_LOG_FILE);
	  exit (-1);
	}
  else
    {

	line_counts= 0L;
	memset (fbuf, 0x0, BMAX);

	name_hd=NULL;
	ip_hd=NULL;

sqlsock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,select_status,CONFIG_HOSTID);
sql_select_query(sqlsock,sql);
logp_log(LOG_LEVEL_ERR,sql);

if(sql_num_rows(sqlsock)!=0)
{	sql_fetch_row(sqlsock);

      if(sqlsock)
        {
        havelast=SUCCEED;
         if(sqlsock->row[0])
        {
    
	havelast=SUCCEED;
        success=atoll(sqlsock->row[0]);
	referral=atoll(sqlsock->row[1]);
	nxrrset=atoll(sqlsock->row[2]);
	nxdomain=atoll(sqlsock->row[3]);
	recursion=atoll(sqlsock->row[4]);
	failure=atoll(sqlsock->row[5]);
	duplicate=atoll(sqlsock->row[6]);
	dropped=atoll(sqlsock->row[7]);
	servfail=atoll(sqlsock->row[8]);
	redirect=atoll(sqlsock->row[9]);
        }
    }
}

sql_finish_query(sqlsock);
release_sql_socket(sqlsock);

fseek(fh,-BMAX,SEEK_END);
fgets(fbuf,BMAX,fh);

  while (fgets (fbuf, BMAX, fh) != NULL)
  {
  if(tmpchar=strstr(fbuf,"noerror =>"))
  	{
		if(1==sscanf(tmpchar+11,"'%lu'",&bsuccess))
			{
		  	      total_status++;
			}
  	}
  else if (tmpchar=strstr(fbuf,"recursive-lookups =>"))
  	{
	  	  if(1==sscanf(tmpchar+21,"'%lu'",&bredirect))
	   	{
	                total_status++;
	   	}
  	}
  else if (tmpchar=strstr(fbuf,"nxdomain =>"))
  	{
	  	 if(1==sscanf(tmpchar+12,"'%lu'",&bnxdomain))
	   	{
	                total_status++;
	   	}
      }
  else if (tmpchar=strstr(fbuf,"servfail =>"))
  	{

	     if(1==sscanf(tmpchar+12,"'%lu'",&bservfail))
	   	{
	                total_status++;
	   	}
	};
   

}

	logp_log(LOG_LEVEL_ERR,"I Got %lu %lu %lu %lu\n",bsuccess,brecursion,bnxdomain,bservfail);
  }

if(total_status=4)
{

//with statuslog marked old
inssock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,cins_status_last,
	CONFIG_HOSTID,bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bduplicate,bdropped,bservfail,bredirect,cur_date);
if(havelast==SUCCEED)
	snprintf(sql,sizeof(sql)-1, cins_update_status_last,
		bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bduplicate,bdropped,bservfail,bredirect,CONFIG_HOSTID);

//  logp_log(LOG_LEVEL_ERR,"|===| %s\n",sql);
sql_query(inssock,sql);

	if(havelast==SUCCEED)
	{
		bsuccess-=success;
		breferral-=referral;
		bnxrrset-=nxrrset;
		bnxdomain-=nxdomain;
		brecursion-=recursion;
		bfailure-=failure;
		bduplicate-=duplicate;
		bservfail-=servfail;
		bdropped-=dropped;
		bredirect-=redirect;

	snprintf(sql,sizeof(sql)-1, cins_status,
		CONFIG_HOSTID,bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bduplicate,bdropped,bservfail,bredirect,cur_date);	
//	logp_log(LOG_LEVEL_ERR,"|===***| %s\n",sql);
	sql_query(inssock,sql);

	}
	sql_finish_query(inssock);
	release_sql_socket(inssock);
}
else logp_log(LOG_LEVEL_ERR,"No append statuslog, Quit program %s\n",progname);
  
exit(0);
}
else if(strstr(progname,"statuslog")!=0)
{

/*
>success 6654815260
>referral 452817824
>nxrrset 155919406
>nxdomain 553276952
>recursion 1592081111
>failure 475588639
>duplicate 121993134
>dropped 64922064
>servfail 475482765
>redirect 149424602
*/

s_success=s_referral=s_nxrrset=s_nxdomain=s_recursion=s_failure=SUCCEED;
bsuccess=breferral=bnxrrset=bnxdomain=brecursion=bfailure=bduplicate=bdropped=bservfail=bredirect=0L;
success=referral=nxrrset=nxdomain=recursion=failure=duplicate=dropped=servfail=redirect=0L;
total_status=SUCCEED;

if ((fh = fopen (DNS_LOG_FILE, "r")) == NULL)
        {
          printf ("Error: can't open file %s.\n",DNS_LOG_FILE);
          exit (-1);
        }
else
{

line_counts= 0L;
memset (fbuf, 0x0, BMAX);

name_hd=NULL;
ip_hd=NULL;
snprintf(sql,sizeof(sql)-1,select_status,CONFIG_HOSTID);
sqlsock=get_sql_socket();
sql_select_query(sqlsock,sql);

if(sql_num_rows(sqlsock)!=0)
{
   sql_fetch_row(sqlsock);
      if(sqlsock)
        {
        havelast=SUCCEED;
         if(sqlsock->row[0])
        {
        success=atoll(sqlsock->row[0]);
        referral=atoll(sqlsock->row[1]);
        nxrrset=atoll(sqlsock->row[2]);
        nxdomain=atoll(sqlsock->row[3]);
        recursion=atoll(sqlsock->row[4]);
        failure=atoll(sqlsock->row[5]);
        duplicate=atoll(sqlsock->row[6]);
        dropped=atoll(sqlsock->row[7]);
        servfail=atoll(sqlsock->row[8]);
        redirect=atoll(sqlsock->row[9]);
        }
        }
}
sql_finish_select_query(sqlsock);
release_sql_socket(sqlsock);

fseek(fh,-MAX_AUTH_QUERY_LEN,SEEK_END);
fgets(fbuf,BMAX,fh);

  while (fgets (fbuf, BMAX, fh) != NULL)
  {
  
   if(1==sscanf(fbuf,"success %lu",&bsuccess))
   	{
      		      total_status++;
   	}
   else if(1==sscanf(fbuf,"referral %lu",&breferral))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"nxrrset %lu",&bnxrrset))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"nxdomain %lu",&bnxdomain))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"recursion %lu",&brecursion))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"failure %lu",&bfailure))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"duplicate %lu",&bduplicate))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"dropped %lu",&bdropped))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"servfail %lu",&bservfail))
   	{
                total_status++;
   	}
   else if(1==sscanf(fbuf,"redirect %lu",&bredirect))
   	{
                total_status++;
   	}
   ;
   
  }

   logp_log(LOG_LEVEL_ERR,"I Got %lu %lu %lu %lu\n",bsuccess,brecursion,bnxdomain,bservfail);

}
if(total_status>4)
{

//with statuslog marked old
inssock=get_sql_socket();

snprintf(sql,sizeof(sql)-1, ins_status_last,
	CONFIG_HOSTID,bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bduplicate,bdropped,bservfail,bredirect,cur_date);
if(havelast==SUCCEED)
	snprintf(sql,sizeof(sql)-1, update_status_last,
			bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bduplicate,bdropped,bservfail,bredirect,CONFIG_HOSTID);

logp_log(LOG_LEVEL_ERR,"|| %s\n",sql);

      sql_query(inssock,sql);

if(havelast==SUCCEED)
	{
		bsuccess-=success;
		breferral-=referral;
		bnxrrset-=nxrrset;
		bnxdomain-=nxdomain;
		brecursion-=recursion;
		bfailure-=failure;
		bduplicate-=duplicate;
		bservfail-=servfail;
		bdropped-=dropped;
		bredirect-=redirect;

	snprintf(sql,sizeof(sql)-1, ins_status,
		CONFIG_HOSTID,bsuccess,breferral,bnxrrset,bnxdomain,brecursion,bfailure,bduplicate,bdropped,bservfail,bredirect,cur_date);
	sql_query(inssock,sql);
	}


	sql_finish_query(inssock);
	release_sql_socket(inssock);
}
else logp_log(LOG_LEVEL_ERR,"No append statuslog, Quit program %s\n",progname);
exit(0);
}


sqlsock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,idquery,cur_date);
logp_log(LOG_LEVEL_ERR,sql);

sql_select_query(sqlsock,sql);
if(sql_num_rows(sqlsock)!=0)
{
	sql_fetch_row(sqlsock);
	        
	if(sqlsock)
	{    
	      if(sqlsock->row[0])
		{
			queryid=atoll(sqlsock->row[0]);
			queryid++;
		}
		 else
		 {

		snprintf(sql,sizeof(sql)-1,idquery2);
		logp_log(LOG_LEVEL_ERR,sql);

		sql_select_query(sqlsock,sql);
		if(sql_num_rows(sqlsock)!=0)
		{
			sql_fetch_row(sqlsock);
			        
			if(sqlsock)
			{    
			      if(sqlsock->row[0])
				{
					queryid=atoll(sqlsock->row[0]);
					queryid++;
				}
				 else
				 {
				        queryid=1L;
					inssock=get_sql_socket();
					snprintf(sql,sizeof(sql)-1,ins_querylog,queryid,CONFIG_HOSTID,cur_date);
					sql_query(inssock,sql);
					logp_log(LOG_LEVEL_ERR,sql);

					sql_finish_query(inssock);
					release_sql_socket(inssock);
				 }
			}

		}
		
		inssock=get_sql_socket();
		snprintf(sql,sizeof(sql)-1,createiptbl,cur_daily);
		sql_query(inssock,sql);
		logp_log(LOG_LEVEL_ERR,sql);

		snprintf(sql,sizeof(sql)-1,createnametbl,cur_daily);
		sql_query(inssock,sql);
		logp_log(LOG_LEVEL_ERR,sql);

		sql_finish_query(inssock);
		release_sql_socket(inssock);
	 }
   }

}

sql_finish_select_query(sqlsock);
release_sql_socket(sqlsock);

inssock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,ins_querylog,queryid,CONFIG_HOSTID,cur_date);
sql_query(inssock,sql);
logp_log(LOG_LEVEL_ERR,sql);

sql_finish_query(inssock);
release_sql_socket(inssock);

sqlsock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,chk_ip_latency);
sql_select_query(sqlsock,sql);
if(sql_num_rows(sqlsock)!=0)
{	sql_fetch_row(sqlsock);
        CONFIG_IPLOW=atoll(sqlsock->row[0]);
}

sql_finish_select_query(sqlsock);
release_sql_socket(sqlsock);

sqlsock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,chk_name_latency);
sql_select_query(sqlsock,sql);
if(sql_num_rows(sqlsock)!=0)
{	sql_fetch_row(sqlsock);
         CONFIG_ASLOW=atoll(sqlsock->row[0]);
}
sql_finish_select_query(sqlsock);
release_sql_socket(sqlsock);

 iparray = malloc (INTMAX*sizeof (IARRAY *));
  for (i = 0; i < INTMAX; i++)
    iparray[i] = malloc (INTMAX*sizeof (IARRAY));

  for(i=0; i<M1LEN; i++) m1table[i]=i;
      for(i=0;i<M1LEN;i++) 
         {
            ranhp=(int)random()&(M1LEN-1);
            rantmp=m1table[ranhp];
            m1table[ranhp]=m1table[i];
            m1table[i]=rantmp;
         }
	  
for(j=0;j<MXM1;j++)  
  for(i=0; i<M2LEN; i++)
     m2table[j][i]=i;

for(j=0;j<MXM1;j++) 
        for(i=0;i<M2LEN;i++) 
         {
            ranhp=(int)random()&(M2LEN-1);
            rantmp=m2table[j][ranhp];
            m2table[j][ranhp]=m2table[j][i];
            m2table[j][i]=rantmp;
         }


  for (i = 0; i < INTMAX; i++)
           {
           ap=&namearray[i];
           ap->name=NULL;
           ap->ncount=0L;
           ap->next=NULL;
           }

//

ipl_hd=NULL;
ipl_cur=NULL;
sqlsock=get_sql_socket();
snprintf(sql,sizeof(sql)-1,get_iplist,cur_date);
sql_select_query(sqlsock,sql);
if(sql_num_rows(sqlsock)!=0)
{

 while(sql_fetch_row(sqlsock))
	{
	ipl_next=malloc(sizeof(IPL));
	if(ipl_hd==NULL)
		{
		  ipl_hd=ipl_cur=ipl_next;
		}
	else
		{	ipl_cur->next=ipl_next;
			ipl_cur=ipl_cur->next;
		}
	ipl_cur->next=NULL;
	
	if(sqlsock->row[0])
		{
		ipl_cur->ip_id=atoll(sqlsock->row[0]);
		ipl_cur->ipstart=strdup(sqlsock->row[1]);
		ipl_cur->ipstop=strdup(sqlsock->row[2]);
		}
	}
}

sql_finish_select_query(sqlsock);
release_sql_socket(sqlsock);


ipl_cur=ipl_hd;
while(ipl_cur!=NULL)
{
      ipl_label1=xaton(ipl_cur->ipstart);
      ipl_label2=xaton(ipl_cur->ipstop);
	if((ipl_label1!=FAIL)&&(ipl_label2!=FAIL))
	 {
	   if(ipl_label1<ipl_label2)
	    for(ipl_label=ipl_label1;ipl_label<ipl_label2;ipl_label++)
	    	{
		      iparray[ipl_label]->ip_id=ipl_cur->ip_id;
	    	}
	  }

      ipl_cur=ipl_cur->next;	
}

//
//22-May-2007 06:13:40.861 client 222.73.19.182#46349: query: peanuter.xicp.net IN TXT +
if ((fh = fopen (DNS_LOG_FILE, "r")) == NULL)
            {
              printf ("Error: can't open file %s.\n",DNS_LOG_FILE);
              exit (-1);
            }
  else
    {

  line_counts= 0L;
  memset (fbuf, 0x0, BMAX);

name_hd=NULL;
ip_hd=NULL;

  while (fgets (fbuf, BMAX, fh) != NULL)
    {
      i=35;
       while(fbuf[i]!='#')
       	{
       	  i++;
       	}
	   
    fbuf[i]='\0';

	  ip_cdns = malloc (sizeof (ICDNS));				
	  memset (ip_cdns, 0x0, sizeof (struct COMB_DNS));
	  name_cdns = malloc (sizeof (ICDNS));
	  memset (name_cdns->name, 0x0, sizeof (name_cdns->name));

	if(3!=sscanf (fbuf, "%s %s client %s#%s: query: %s IN %s", &tmp1,&tmp2, ip_cdns->ip)) continue;
	if(3!=sscanf(fbuf+i+1, "%s query: %s %s",&tmp1,&name_cdns->name,&tmp2)) continue;
	
          if (dxaton(iparray, ip_cdns->ip) == 0)
            {
              if (ip_hd == NULL)
                {
                  ip_hd = ip_cur = ip_cdns;
                }
              else
                {
                 ip_cur->next=ip_cdns;
                 ip_cur=ip_cur->next;
                }
            }
          else free(ip_cdns);

          ranhp=xnamehash(namearray,name_cdns->name);

          if(ranhp==FOUND) 
           {
            free (name_cdns);
           }
		  
		line_counts++;
			
		memset (fbuf, 0x0, BMAX);

         }


logp_log(LOG_LEVEL_CRIT,"%lu  clientip\n",line_counts);
 
below_ip=0L;
ip_cnt=0L;
ip_cur=ip_hd;
inssock=get_sql_socket();
while (ip_cur != NULL)
        {
          ip_cdns = ip_cur->next;
          sxcnt=sxarray(iparray,ip_cur->ip);
          ip_cnt++;
          if(sxcnt<=CONFIG_IPLOW) below_ip++;
          else
          {
		snprintf(sql,MAX_STRING_LEN,ins_ip,cur_daily,queryid,ip_cur->ip,sxcnt,cur_date);
		sql_query(inssock,sql);

          }
          free (ip_cur);
          ip_cur = ip_cdns;
        }
	   

logp_log(LOG_LEVEL_CRIT,"%lu ips %lu  belows\n",ip_cnt,below_ip);

below_name=0L;
name_cnt=0L;
  for (i = 0; i < INTMAX; i++)
           {
           ap=&namearray[i];
 
           name_cur=ap;
	   tmpint=0;
	   while(name_cur!=NULL)
	   	{
		   	 if(name_cur->name)
		   	 {
		   	 tmpint++;
		   	 name_cnt++;
		          if(name_cur->ncount<=CONFIG_ASLOW)  below_name++;
			  else
			  	{
			  		snprintf(sql,MAX_STRING_LEN,ins_name,cur_daily,queryid,name_cur->name,name_cur->ncount,cur_date);
					sql_query(inssock,sql);
			  	}
		   	 }
			 
			 name_cur=name_cur->next;
	   	}
            if(tmpint>maxline){ maxline=tmpint; j=i;}
	    if(tmpint) maxslots++;
	    if(tmpint>CONFIG_ASLOW) logp_log(LOG_LEVEL_MSG,"%d over all %d ",tmpint,i);
           }
	   
     }

snprintf(sql,sizeof(sql)-1,update_querylog,line_counts,ip_cnt,name_cnt,below_ip,below_name,queryid);
sql_query(inssock,sql);

ipl_cur=ipl_hd;
while(ipl_cur!=NULL)
{
      ipl_label1=xaton(ipl_cur->ipstart);
      ipl_label2=xaton(ipl_cur->ipstop);
	if((ipl_label1!=FAIL)&&(ipl_label2!=FAIL))
	 {
	   ipl_count=0L;
	   if(ipl_label1<ipl_label2)
	    {
	    for(ipl_label=ipl_label1;ipl_label<ipl_label2;ipl_label++)
	    	{
		     ipl_count+=iparray[ipl_label]->ncount;			 
	    	}
	        	snprintf(sql,sizeof(sql)-1,ins_ipsummary,iparray[ipl_label1]->ip_id,ipl_count);
			sql_query(inssock,sql);
	      }
	
	  }

      ipl_cur=ipl_cur->next;	
}


snprintf(sql,sizeof(sql)-1,"commit");
sql_query(inssock,sql);

sql_finish_query(inssock);
release_sql_socket(inssock);

logp_log(LOG_LEVEL_CRIT,"%lu names %lu belows max_chains %d hashslots %d\n ", name_cnt,below_name,maxline,maxslots);

exit(0);
}


